// 怎样定义一个类
#include <iostream>
#include <string>

class DefineAClass
{
private:
    std::string company;
    long shares;
    double share_val;
    double total_val;

    // 本身成为内联函数: inline void DefineAClass::set_tot()
    void set_tot(){
        total_val = shares * share_val;
    }
public:
    DefineAClass(/* args */);
    // DefineAClass(){
    //     std::cout << "none parameters constructor invoked" << std::endl;
    // };
    DefineAClass(const std::string &co, long n, double pr);
    // ~DefineAClass();
    ~DefineAClass();

    void acquire(const std::string &co,long n,double pr);
    void buy(long num,double price);
    void sell(long num,double price);
    void update(double price);
    void show();
    // some other function
};
// C++关键字class指出这是一个类设计!
// 这里的class和之前使用过的typename(在模板中使用的那个)不是一个东西!!!!   在定义类的时候不能使用typename替换class关键字!!
// 上面的声明使得我们具备了声明一个叫做DefineAClass的类的能力

// 创建一个这样的类的对象
// DefineAClass aclass;

// 访问控制
// 新的关键字public 和 private
// 这两个关键字(其实还有protected)描述了对类成员的访问控制. 使用类对象的程序都可以直接访问公共部分,但是只能通过公有成员函数(或者友元函数)进行私有成员的访问
// 不必在类声明上使用关键字private,因为这是类对象的默认访问权限!!!   上文只是为了强调数据隐藏的概念,显式的使用了private


// 实现类成员函数
// 1. 定义成员函数时，使用作用域解析运算符来标识函数所属的类。
// 2. 类方法可以访问类的private组件。

// void DefineAClass::update(double price)
// 1. 这种表示方法意味着我们定义的update()函数是DefineAClass的成员函数,而且我们还可以将另一个类的成员函数也命名为update(),比如Stock::update();
// 这样,作用域解析运算符(::) 确定了方法定义对应类的身份, 我们说标识符update具有类作域,  DefineAClass类的其他成员函数，不必使用作用域解析运算符，就可以使用update方法, 你为他们同属于一个类，因此对update是可见的.
// 如果想要在类声明和方法定义之外，使用update需要采取特殊措施，稍后将做介绍。

// 2. 方法可以访问类的私有成员, 如果试图使用非成员函数访问这些数据成员，编译器将会禁止这样做。(友元函数例外)
// std::cout << "Company: " << company 
//         << " Shares: " << shares
//         << " Share Price: $" << share_val
//         << " Total Price: $" << total_val << std::endl;
// 其中company,shares等是DefineAClass中的私有成员,编译器将会禁止这样做


// 类和结构的区别
// 
// 类描述看上去很像是包含成为函数以及public和private可见性标签的结构声明。实际上C++对结构进行了扩展,使之具有与类相同的特性。
// 他们之间唯一的区别是:结构的默认访问权限是public而类为private!!!!!
// C++程序员通常使用类来实现类描述，而把结构限制为只表示纯粹的数据对象，常被称为老式数据Plain Old Data.
// 另外，C语言中，空结构体的大小为0，而C++中空结构体（属于空类）的大小为1。
//         C++中空类的大小为1的原因：
// 空类也可以实例化，类实例化出的每个对象都需要有不同的内存地址，为使每个对象在内存中的地址不同，所以在类中会加入一个隐含的字节。

// 3. 内联方法(函数)
// 其定位于类方法中的函数都将会自动成为内联函数,比如说set_tot(),他是一个私有函数,不是公共接口中的一部分
// 如果愿意也可以将一个位于类之外的函数定义为内联函数(使用关键字inline),只需要使用类名::修饰一下
// inline void DefineAClass::set_tot(){
//     total_val = shares * share_val;
// }
// 根据改写规则,在类声明中定义方法等同于用原型替换方法定义,然后在类声明的后面将定义改写为内联函数

// 上面public函数的具体实现在 39OOP-usingClass.cpp中,本文件是一个头文件(.h/.hpp)


